package com.tfleo.mealssenger;

import com.tfleo.mealssenger.R;
import com.tfleo.mealssenger.service.ChatService;
import com.tfleo.mealssenger.utility.ImageTools;
import com.tfleo.mealssenger.utility.NetworkTools;
import com.tfleo.mealssenger.utility.SecurityTools;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;

import org.apache.http.NameValuePair;
import org.apache.http.client.HttpClient;
import org.apache.http.client.ResponseHandler;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.BasicResponseHandler;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.message.BasicNameValuePair;
import org.json.JSONException;
import org.json.JSONObject;

import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.graphics.Bitmap;
import android.graphics.Typeface;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Environment;
import android.provider.MediaStore;
import android.provider.MediaStore.Images.Media;
import android.text.method.PasswordTransformationMethod;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.ImageView.ScaleType;
import android.widget.Toast;

/**
 * Register new user to Mealssenger.
 * 
 * @author Theodore Felix Leo
 *
 */
public class RegisterActivity extends Activity {
	private static final String UPLOAD_URL = 
			Main.SERVER_URL + "image_upload.php?op=0"; //op=0 store in 'SERVER/img/user/'
	private static final int CAMERA_REQUEST = 1;

	private ImageView vProfileImage;
	private EditText vEmailEntry;
	private EditText vPasswordEntry;
	private EditText vNameEntry;
	private Button vSubmitBtn;

	private Context mContext;

	private File mImageDir;
	private File mCurImageDir;
	private File mRoot;
	private Uri mOutputFileUri;
	private Bitmap mPhoto;

	private int mLastInsertId;

	private SharedPreferences mSharedPref;
	private SharedPreferences.Editor mPrefEditor;

	//These are used in case filename uploaded set to be the same with local filename
	//Now: image filename in server is [ID].jpg
	private String mImageFileName;
	//private String mCurImageFileName;

	private boolean mImgAvailable = false;

	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.register_layout);
		mContext = this;

		//Root directory to store image
		mRoot = new File(Environment.getExternalStorageDirectory() + File.separator 
				+ "Mealssenger" + File.separator);
		mRoot.mkdirs();

		mSharedPref = getSharedPreferences(Main.USER_DATA, MODE_PRIVATE);
		mPrefEditor = mSharedPref.edit();

		//Filename for image using random number
		//TODO: handle name conflict
		Random filename = new Random();
		mImageDir = new File(mRoot, Integer.toString(filename.nextInt()) + ".jpg");
		mOutputFileUri = Uri.fromFile(mImageDir);

		vNameEntry = (EditText) findViewById(R.id.name_entry);
		vEmailEntry = (EditText) findViewById(R.id.email_entry);
		vPasswordEntry = (EditText) findViewById(R.id.pass_entry);
		vPasswordEntry.setTypeface(Typeface.DEFAULT);
	    vPasswordEntry.setTransformationMethod(new PasswordTransformationMethod());

		vProfileImage = (ImageView) findViewById(R.id.image);
		vProfileImage.setOnClickListener(new OnClickListener() {
			public void onClick(View v) {
				if(mPhoto != null) {
					mPhoto.recycle();
					System.gc(); //TODO: see whether this can be removed
				}

				Random filename = new Random();
				mImageFileName = Integer.toString(filename.nextInt()) + ".jpg";
				mImageDir = new File(mRoot, mImageFileName);
				mOutputFileUri = Uri.fromFile(mImageDir);

				System.gc(); //TODO: see whether this can be removed
				Intent i = new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE); 
				i.putExtra(MediaStore.EXTRA_OUTPUT, mOutputFileUri);
				startActivityForResult(i, CAMERA_REQUEST); 
			}
		});


		vSubmitBtn = (Button) findViewById(R.id.submit);
		vSubmitBtn.setOnClickListener(new OnClickListener() {
			public void onClick(View v) {
				String email, password, name;

				if((email = vEmailEntry.getText().toString()).trim().equals("")) {
					Toast.makeText(mContext, "Invalid email address!", 
							Toast.LENGTH_SHORT).show();
					return;
				}
				/*if((password = vPasswordEntry.getText().toString()).trim().equals("")) {
					Toast.makeText(mContext, "[Err:10] Invalid password!", Toast.LENGTH_SHORT).show();
					return;
				}*/
				if((password = vPasswordEntry.getText().toString()).trim().length() < 6) {
					Toast.makeText(mContext, "Password must be minimum 6 characters long!", 
							Toast.LENGTH_SHORT).show();
					return;
				}

				if((name = vNameEntry.getText().toString()).trim().equals("")) {
					Toast.makeText(mContext, "Invalid user name!", 
							Toast.LENGTH_SHORT).show();
					return;
				}

				SubmitTask task = new SubmitTask();
				task.execute(new String[] {email, password, name});
			}
		});

		if(!NetworkTools.isNetworkAvailable(mContext)) {
			Toast.makeText(mContext, "Network is currently unavailable", 
					Toast.LENGTH_LONG).show();
			Log.e("RegisterActivity", "[NetworkProblem] Network is unavailable");
		}
	}

	@Override
	protected void onActivityResult(int requestCode, int resultCode, Intent data) {  
		if (requestCode == CAMERA_REQUEST) {  
			if (resultCode == RESULT_OK) {
				try {
					System.gc();
					//mPhoto.recycle();
					getContentResolver().notifyChange(mOutputFileUri, null);       			
					ImageTools.compress(getContentResolver(), mOutputFileUri, mImageDir);

					//Set thumbnail
					mPhoto = Media.getBitmap(getContentResolver(), mOutputFileUri);
					vProfileImage.setImageBitmap(mPhoto);
					vProfileImage.setScaleType(ScaleType.CENTER_CROP);

					mCurImageDir = mImageDir;
					//mCurImageFileName = mImageFileName;
					mImgAvailable = true;
				} catch(FileNotFoundException e) {
					e.printStackTrace();
				} catch(IOException e) {
					e.printStackTrace();
				} catch(Exception e) {
					e.printStackTrace();
				}

			} else if (resultCode == RESULT_CANCELED) {
				if(mImgAvailable) {
					//Reuse last image if available
					mImageDir = mCurImageDir;
					//mImageFileName = mCurImageFileName;
					mOutputFileUri = Uri.fromFile(mImageDir);
					try {
						getContentResolver().notifyChange(mOutputFileUri, null);       			

						mPhoto = Media.getBitmap(getContentResolver(), mOutputFileUri);
						vProfileImage.setImageBitmap(mPhoto);
						vProfileImage.setScaleType(ScaleType.CENTER_CROP);

						mCurImageDir = mImageDir;
						mImgAvailable = true;
					} catch(FileNotFoundException e) {
						e.printStackTrace();
					} catch(IOException e) {
						e.printStackTrace();
					} catch(Exception e) {
						e.printStackTrace();
					}
				}
			} else {
				Toast.makeText(mContext, "[Err:40] Failed to take picture!", Toast.LENGTH_SHORT).show();
			}
		}  
	} 

	private boolean addUser(String email, String password, String name) {
		HttpClient httpclient = new DefaultHttpClient();
		HttpPost httppost = new HttpPost(Main.SERVER_URL + "register.php");

		try {
			List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>(2);
			nameValuePairs.add(new BasicNameValuePair("email", email));
			nameValuePairs.add(new BasicNameValuePair("password", password));
			nameValuePairs.add(new BasicNameValuePair("name", name));
			nameValuePairs.add(new BasicNameValuePair("has_image", Boolean.toString(mImgAvailable)));
			httppost.setEntity(new UrlEncodedFormEntity(nameValuePairs));

			//Execute HTTP Post Request
			ResponseHandler<String> responseHandler = new BasicResponseHandler();
			String body = httpclient.execute(httppost, responseHandler);
			JSONObject jo = new JSONObject(body);

			//Image file name in server is equal to its ID
			if((mLastInsertId = jo.getInt("code")) > 0) {
				Log.i("RegisterActivity", "[UserID] " + mLastInsertId);
				if(mImgAvailable) {
					ImageTools.upload(mCurImageDir, UPLOAD_URL, Integer.toString(mLastInsertId) + ".jpg");
				}

				mPrefEditor.putString(Main.CHAT_ID, Integer.toString(mLastInsertId));
				mPrefEditor.putString(Main.TOKEN, SecurityTools.encrypt(SecurityTools.MASTER_KEY, password));
				mPrefEditor.commit();
				ChatService.actionRegister(getApplicationContext());

				return true;
			} else {
				return false;
			}
		} catch(JSONException e){
			e.printStackTrace();
		} catch(IOException e) {
			e.printStackTrace();
		} catch(Exception e) {
			e.printStackTrace();
		}

		return false;
	}

	/**
	 * Asynchronous task to handle submission of data to server.
	 */
	private class SubmitTask extends AsyncTask<String, Void, Boolean> {
		@Override
		protected Boolean doInBackground(String... params) {
			return addUser(params[0], params[1], params[2]);
		}

		@Override
		protected void onPostExecute(Boolean result) {
			if(result) {
				setResult(RESULT_OK);
				mPrefEditor.commit();
				finish();
			} else {
				Toast.makeText(getApplicationContext(), "Failed to submit to server", 
						Toast.LENGTH_SHORT).show();
			}
		}

	}
}
